﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Printing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Notoric.Gui.Windows;

namespace Notoric.Gui.Controls
{
    /// <summary>
    /// Interaction logic for PrintBackstageTab.xaml
    /// </summary>
    public partial class PrintBackstageTab : UserControl
    {
        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="PrintBackstageTab"/> class.
        /// </summary>
        public PrintBackstageTab()
        {
            PrintDlg = new PrintDialog();

            InitializeComponent();
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Clears the tree view selection.
        /// </summary>
        /// <param name="ic">
        /// <para>
        /// Type: <see cref="ItemCollection"/>
        /// </para>
        /// <para>
        /// The collection of tree view items.
        /// </para>
        /// </param>
        /// <param name="icg">
        /// <para>
        /// Type: <see cref="ItemContainerGenerator"/>
        /// </para>
        /// <para>
        /// The item container generator used in the tree view.
        /// </para>
        /// </param>
        private void ClearTreeViewItemsControlSelection(ItemCollection ic, ItemContainerGenerator icg)
        {
            if ((ic != null) && (icg != null))
                for (int i = 0; i < ic.Count; i++)
                {
                    TreeViewItem tvi = icg.ContainerFromIndex(i) as TreeViewItem;
                    if (tvi != null)
                    {
                        ClearTreeViewItemsControlSelection(tvi.Items, tvi.ItemContainerGenerator);
                        tvi.IsSelected = false;
                    }
                }
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Occurs when the collection of open projects has changed.
        /// </summary>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void Projects_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            var collection = (ObservableCollection<ViewModel.Elements.Project>)sender;
            if (collection.Count > 0)
                PrintTab_ScoresTree.ItemsSource = collection[0].GetRootDirectory(ViewModel.Elements.RootDirectory.Scores).Children;
            else
                PrintTab_ScoresTree.ItemsSource = null;
        }

        /// <summary>
        /// Occurs when the control has been loaded.
        /// </summary>
        /// <param name="sender">Object where the event handler is attached</param>
        /// <param name="e">Event data</param>
        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            if (PrintTab_Printers_ComboBox != null)
            {
                PrintTab_Printers_ComboBox.ItemsSource = new LocalPrintServer().GetPrintQueues(
                    new EnumeratedPrintQueueTypes[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections }
                    );

                if (PrintTab_Printers_ComboBox.Items != null)
                {
                    PrintQueue defaultPrinter = null;
                    foreach (PrintQueue queue in PrintTab_Printers_ComboBox.Items)
                    {
                        if (queue.FullName == PrintDlg.PrintQueue.FullName)
                        {
                            defaultPrinter = queue;
                            break;
                        }
                    }

                    PrintTab_Printers_ComboBox.SelectedItem = defaultPrinter;
                }
            }

            DependencyPropertyDescriptor backstageOpenDescriptor = DependencyPropertyDescriptor.FromProperty(Fluent.Ribbon.IsBackstageOpenProperty, typeof(Fluent.Ribbon));
            backstageOpenDescriptor.AddValueChanged(((MainWindow)App.Current.MainWindow).Ribbon, new EventHandler(IsBackstageOpenProperty_ValueChanged));

            if (projectExplorer == null && App.Current.MainWindow != null && ((MainWindow)App.Current.MainWindow).ProjectExplorer != null)
            {
                projectExplorer = ((MainWindow)App.Current.MainWindow).ProjectExplorer;
                projectExplorer.Projects.CollectionChanged += new NotifyCollectionChangedEventHandler(Projects_CollectionChanged);

                if (projectExplorer.Projects.Count > 0)
                    PrintTab_ScoresTree.ItemsSource = projectExplorer.Projects[0].GetRootDirectory(ViewModel.Elements.RootDirectory.Scores).Children;
            }
        }

        /// <summary>
        /// Handles the ValueChanged event of the IsBackstageOpenProperty.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void IsBackstageOpenProperty_ValueChanged(object sender, EventArgs e)
        {
            if (!((MainWindow)App.Current.MainWindow).Ribbon.IsBackstageOpen)
                ClearTreeViewItemsControlSelection(PrintTab_ScoresTree.Items, PrintTab_ScoresTree.ItemContainerGenerator);
        }

        /// <summary>
        /// Occurs when the user selects another printer.
        /// </summary>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void PrintTab_Printers_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var copyCount = (int)PrintTab_CopiesSpinner.Value;

            PrintDlg.PrintQueue = (PrintQueue)PrintTab_Printers_ComboBox.SelectedItem;
            PrintDlg.PrintTicket.CopyCount = copyCount;
        }

        /// <summary>
        /// Occurs when the user clicks on the "Printer Settings" command.
        /// </summary>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void ShowPrinterSettings_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (PrintDlg.ShowDialog() == true)
            {
                if (PrintDlg.PageRangeSelection == PageRangeSelection.UserPages)
                {
                    var paginator = new PageRangeDocumentPaginator(PrintTab_PrintPreview.Document.DocumentPaginator, PrintDlg.PageRange);
                    PrintDlg.PrintDocument(paginator, ((ViewModel.Elements.Score)PrintTab_ScoresTree.SelectedItem).DisplayName);
                }
                else
                    PrintDlg.PrintDocument(PrintTab_PrintPreview.Document.DocumentPaginator, ((ViewModel.Elements.Score)PrintTab_ScoresTree.SelectedItem).DisplayName);
            }

            PrintTab_CopiesSpinner.Value = (uint)PrintDlg.PrintTicket.CopyCount;
            if (PrintDlg.PageRangeSelection == PageRangeSelection.UserPages)
            {
                PrintTab_PageRangeSelection_ComboBox.SelectedIndex = 1;
                PrintTab_SelectedPages.Text = PrintDlg.PageRange.ToString();
            }
            else
                PrintTab_PageRangeSelection_ComboBox.SelectedIndex = 0;
        }

        /// <summary>
        /// Occurs when the user has selected another score to print.
        /// </summary>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void PrintTab_ScoresTree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
        {
            if (PrintTab_ScoresTree.SelectedItem is ViewModel.Elements.Score)
            {
                PrintTab_Print_Button.IsEnabled = true;
                ShowPrinterSettings.IsEnabled = true;
                PrintDlg.MinPage = 1;
                PrintDlg.MaxPage = (uint)PrintTab_PrintPreview.PageCount;
                PrintDlg.UserPageRangeEnabled = true;
                PrintTab_PageRangeSelection_ComboBox.SelectedIndex = 0;
            }
            else
            {
                PrintTab_Print_Button.IsEnabled = false;
                ShowPrinterSettings.IsEnabled = false;
            }
        }

        /// <summary>
        /// Occurs when print button has been clicked.
        /// </summary>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void PrintTab_Print_Button_Click(object sender, RoutedEventArgs e)
        {
            if (PrintDlg.PageRangeSelection == PageRangeSelection.UserPages)
            {
                var paginator = new PageRangeDocumentPaginator(PrintTab_PrintPreview.Document.DocumentPaginator, PrintDlg.PageRange);
                PrintDlg.PrintDocument(paginator, ((ViewModel.Elements.Score)PrintTab_ScoresTree.SelectedItem).DisplayName);
            }
            else
                PrintDlg.PrintDocument(PrintTab_PrintPreview.Document.DocumentPaginator, ((ViewModel.Elements.Score)PrintTab_ScoresTree.SelectedItem).DisplayName);
        }

        /// <summary>
        /// Occurs when the user has changed the pange range selection.
        /// </summary>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void PrintTab_PageRangeSelection_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            switch (PrintTab_PageRangeSelection_ComboBox.SelectedIndex)
            {
                case 0:         // All Pages
                    PrintDlg.PageRangeSelection = PageRangeSelection.AllPages;
                    if (PrintTab_SelectedPages != null && PrintTab_SelectedPages.Text != "")
                        PrintTab_SelectedPages.Text = "";
                    break;
                case 1:         // User Pages
                    PrintDlg.PageRangeSelection = PageRangeSelection.UserPages;
                    break;
            }
        }

        /// <summary>
        /// Occurs when the user has typed into the page range text box.
        /// </summary>
        /// <param name="sender">Object that has sent the event</param>
        /// <param name="e">Event data</param>
        private void PrintTab_SelectedPages_KeyUp(object sender, KeyEventArgs e)
        {
            if (PrintTab_PageRangeSelection_ComboBox.SelectedIndex != 1)
                PrintTab_PageRangeSelection_ComboBox.SelectedIndex = 1;

            if (PrintTab_SelectedPages.Text.Contains("-"))
            {
                try
                {
                    var segments = PrintTab_SelectedPages.Text.Split('-');
                    int pageFrom = 1;
                    if (segments.Length > 0)
                        pageFrom = int.Parse(segments[0]);
                    int pageTo = 1;
                    if (segments.Length > 1)
                        pageTo = int.Parse(segments[1]);

                    PrintDlg.PageRange = new PageRange(pageFrom, pageTo);
                }
                catch (Exception)
                {

                }
            }
            else
            {
                try
                {
                    PrintDlg.PageRange = new PageRange(int.Parse(PrintTab_SelectedPages.Text));
                }
                catch (Exception)
                {
                    PrintDlg.PageRange = new PageRange(1);
                }
            }
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the print dialog.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="PrintDialog"/>
        /// </para>
        /// <para>
        /// The print dialog.
        /// </para>
        /// </value>
        public PrintDialog PrintDlg
        {
            get;
            private set;
        }

        #endregion

        #region Private Fields

        /// <summary>
        /// Holds the project explorer instance.
        /// </summary>
        private ProjectExplorer projectExplorer;

        #endregion
    }
}
